package me.magicall.web.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.http.HttpServletResponse;

import me.magicall.cache.ByteArrayBuffer;
import me.magicall.io.CloseableCreater;
import me.magicall.io.CloseableIOCallback;
import me.magicall.io.IOUtil;
import me.magicall.lang.exception.ExceptionHandler;
import me.magicall.util.encode.EncodeUtil;
import me.magicall.util.kit.Kits;

public class UploadDownload {

	/**
	 * 下载文件
	 * 
	 * @param response
	 * @param absolutePath 文件的绝对路径
	 * @throws Exception
	 */
	public static void download(final HttpServletResponse response, final String absolutePath) throws Exception {
		final File f = new File(absolutePath);
		if (!f.exists()) {
			throw new RuntimeException("文件已丢失,请联系管理员");
		}
		final long fileLen = f.length();
		final String fileShortName = Kits.STR.subStringAfterLastSeq(absolutePath, File.separator);

		response.setContentType("application/x-msdownload;charset=UTF-8");
		response.setHeader("Content-Disposition", "attachment;filename=" + EncodeUtil.encode(fileShortName));
		response.setHeader("Content-Length", String.valueOf(fileLen));

		final ByteArrayBuffer buffer = new ByteArrayBuffer((int) fileLen);//XXX:file可能过大否?
		IOUtil.io(new CloseableCreater<InputStream>() {
			@Override
			public InputStream create() throws IOException {
				return new BufferedInputStream(new FileInputStream(f));
			}
		}, new CloseableIOCallback<InputStream>() {
			@Override
			public void callback(final InputStream in) throws IOException {
				final byte[] bs = new byte[2048];
				for (int read = in.read(bs); read != -1; read = in.read(bs)) {
					buffer.append(bs, 0, read);
				}
			}
		}, new ExceptionHandler<IOException>() {
			@Override
			public void handle(final IOException e) {
				if (e instanceof FileNotFoundException) {
					throw new RuntimeException("文件" + fileShortName + "已丢失,请联系管理员。");
				} else {
					throw new RuntimeException("读取文件" + fileShortName + "出错,请稍后再试");
				}
			}
		});

		if (!buffer.isEmpty()) {
			IOUtil.io(new CloseableCreater<OutputStream>() {
				@Override
				public OutputStream create() throws IOException {
					return response.getOutputStream();
				}
			}, new CloseableIOCallback<OutputStream>() {
				@Override
				public void callback(final OutputStream out) throws IOException {
					out.write(buffer.buffer());
					out.flush();
				}
			}, new ExceptionHandler<IOException>() {
				@Override
				public void handle(final IOException e) throws Exception {
					throw new RuntimeException("处理文件" + fileShortName + "出错,请稍后再试");
				}
			});
		}
	}
}
